﻿ #region Disclaimer/Info
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
 //
 //   File:		RequestTimingFilter.cs
 //   Website:		http://dexterblogengine.com/
 //   Authors:		http://dexterblogengine.com/About.ashx
 //   Rev:		1
 //   Created:		19/01/2011
 //   Last edit:		19/01/2011
 //   License:		GNU Library General Public License (LGPL)
 // 
 //   For updated news and information please visit http://dexterblogengine.com/
 //   Dexter is hosted to Codeplex at http://dexterblogengine.codeplex.com
 //   For any question contact info@dexterblogengine.com
 //
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 #endregion

using System;
using System.Diagnostics;
using System.Web.Mvc;

namespace Dexter.Web.Mvc.Filters {
	public class RequestTimingFilter : IActionFilter , IResultFilter {
		#region IActionFilter Members

		/// <summary>
		/// 	Called before an action method executes.
		/// </summary>
		/// <param name = "filterContext">The filter context.</param>
		public void OnActionExecuting ( ActionExecutingContext filterContext ) {
			GetTimer ( filterContext , "action" ).Start ( );
		}

		/// <summary>
		/// 	Called after the action method executes.
		/// </summary>
		/// <param name = "filterContext">The filter context.</param>
		public void OnActionExecuted ( ActionExecutedContext filterContext ) {
			GetTimer ( filterContext , "action" ).Stop ( );
		}

		#endregion

		#region IResultFilter Members

		/// <summary>
		/// 	Called before an action result executes.
		/// </summary>
		/// <param name = "filterContext">The filter context.</param>
		public void OnResultExecuting ( ResultExecutingContext filterContext ) {
			GetTimer ( filterContext , "render" ).Start ( );
		}

		/// <summary>
		/// 	Called after an action result executes.
		/// </summary>
		/// <param name = "filterContext">The filter context.</param>
		public void OnResultExecuted ( ResultExecutedContext filterContext ) {
			var renderTimer = GetTimer ( filterContext , "render" );
			renderTimer.Stop ( );

			var actionTimer = GetTimer ( filterContext , "action" );
			var response = filterContext.HttpContext.Response;

			if ( response.ContentType == "text/html" ) {
				response.Write (
					String.Format (
						"<p>Action '{0} :: {1}', Execute: {2}ms, Render: {3}ms.</p>" ,
						filterContext.RouteData.Values[ "controller" ] ,
						filterContext.RouteData.Values[ "action" ] ,
						actionTimer.ElapsedMilliseconds ,
						renderTimer.ElapsedMilliseconds
						)
					);
			}
		}

		#endregion

		static Stopwatch GetTimer ( ControllerContext context , string name ) {
			string key = string.Concat ( "__timer__" , name );
			if ( context.HttpContext.Items.Contains ( key ) ) {
				return ( Stopwatch ) context.HttpContext.Items[ key ];
			}

			var result = new Stopwatch ( );
			context.HttpContext.Items[ key ] = result;
			return result;
		}
	}
}
